package com.p2p.front.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.p2p.base.cache.Cache;
import com.p2p.base.model.BaseUser;
import com.p2p.base.model.ValidateCodeSend;
import com.p2p.base.model.ValidateCodeSend.BizTypeEnum;
import com.p2p.base.model.ValidateCodeSend.SendEmailTypeEnum;
import com.p2p.base.model.ValidateCodeSend.SendTypeEnum;
import com.p2p.base.result.ValidateCodeSendResult;
import com.p2p.base.service.ValidateCodeSendService;
import com.p2p.base.util.Encrypter;
import com.p2p.base.util.LoginUtil;
import com.p2p.base.util.MD5Util;
import com.p2p.front.dal.dao.UserDao;
import com.p2p.front.dal.model.AuthValue;
import com.p2p.front.dal.model.EmailCode;
import com.p2p.front.dal.model.User;
import com.p2p.front.dal.model.UserInfoAuth.AuthStatus;
import com.p2p.front.enums.UserCreditsType;
import com.p2p.front.service.EmailCodeService;
import com.p2p.front.service.SendInfoService;
import com.p2p.front.service.UserCreditsService;
import com.p2p.front.service.UserInfoAuthService;
import com.p2p.front.service.UserRegisterCheckService;
import com.p2p.front.service.UserRegisterService;
import com.p2p.front.service.UserSequenceService;
import com.p2p.front.util.MobileUtils;
import com.p2p.front.util.SendTextMessageType;
import com.p2p.front.vo.MobileForRedis;
import com.p2p.front.vo.RegisterEmailForRedis;
import com.p2p.front.vo.UserCenterResult;
import com.p2p.front.vo.UserRegisterVo;
import com.p2p.front.vo.UserRegisterVo.RegisterType;
import com.p2p.trans.client.facade.AccountOpenFacade;
import com.p2p.trans.client.result.AccountOpenResult;
import com.p2p.user.enums.UserAuthName;

@Service
public class UserRegisterServiceImpl implements UserRegisterService {

	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	@Resource
	private UserDao userDao;
	@Resource
	private UserSequenceService userSequenceService;
	@Resource
	private SendInfoService sendInfoService;
	@Resource
	private UserInfoAuthService userInfoAuthService;
	@Resource
	private EmailCodeService emailCodeService;
	@Resource
	private Cache defaultCache;
	
	@Resource
	private ValidateCodeSendService validateCodeSendService;
	@Resource
	private UserRegisterCheckService userRegisterCheckService;
	@Resource
	private AccountOpenFacade remotAccountOpenFacade;
	
	@Resource
	private UserCreditsService userCreditsService;

	@Override
	@Transactional
	public void saveUser(User user) {
		userDao.save(user);
	}

	/**
	 * 身份认证做校验
	 * 
	 * @author hongbo
	 * @param userRegisterVo
	 * @return
	 */
	private UserCenterResult checkAuthID(UserRegisterVo userRegisterVo) {
		UserCenterResult result = new UserCenterResult(true,
				new ArrayList<String>());
		String idcard = userRegisterVo.getIdcard();
		String realname = userRegisterVo.getRealname();
		boolean checkIDResult = userRegisterCheckService
				.checkUserIdcardExist(idcard);
		if (checkIDResult) {
			boolean checkResult = sendInfoService.sendIDInfo(idcard, realname);
			if (!checkResult) {
				result.setSuccess(false);
				result.addMsg("身份认证失败");
			}
		} else {
			result.setSuccess(false);
			if (logger.isDebugEnabled()) {
				logger.debug("身份证已存在");
			}
			result.addMsg("身份证已存在");
		}
		return result;
	}

	@Deprecated
	@Override
	@Transactional
	public UserCenterResult doAuthID(UserRegisterVo userRegisterVo) {
		UserCenterResult result = checkAuthID(userRegisterVo);
		if (result.isSuccess()) {
			String uid = userRegisterVo.getUid();
			User authIdUser = new User();
			authIdUser.setUid(userRegisterVo.getUid());
			authIdUser.setRealname(userRegisterVo.getRealname());
			authIdUser.setIdcard(userRegisterVo.getIdcard());
			userDao.update(authIdUser);

			List<AuthValue> authValueList = new ArrayList<AuthValue>();
			AuthValue emailAuth = new AuthValue(UserAuthName.AUTH_REALNAME,
					AuthStatus.AUTHSUCCESS.getAuthStatus());
			authValueList.add(emailAuth);
			userInfoAuthService.saveAuthByAuthValueList(uid, authValueList);
			AccountOpenResult accountOpenResult = remotAccountOpenFacade
					.openAccountForUser(uid, new HashMap<String, Object>());
			if (accountOpenResult.isSuccess()) {
				String accountNo = accountOpenResult.getAccountNo();
				authIdUser.setAccountNo(accountNo);
				userDao.updateAccountNo(authIdUser);
			}
		}

		return result;
	}

	/**
	 * 发送手机验证码
	 */
	@Override
	public UserCenterResult sendSMSCode(String mobileNum, String key,
			BizTypeEnum type, int codeType) {
		UserCenterResult result = new UserCenterResult(true,
				new ArrayList<String>());
		UserCenterResult checkResult = userRegisterCheckService
				.checkMobileOrEmailExist(mobileNum, StringUtils.EMPTY, codeType);
		if (!checkResult.isSuccess()) {
			result.setSuccess(false);
			result.addMsg(checkResult.getMsgs().get(0));
			return result;
		}

		key += mobileNum;
		MobileForRedis oldMobile = (MobileForRedis) defaultCache.getValue(key);
		if (oldMobile != null
				&& StringUtils.isNoneEmpty(oldMobile.getUmobile())) {
			Integer sendTimes = oldMobile.getSendTimes();

			Calendar cal = Calendar.getInstance();
			cal.setTime(oldMobile.getCreateTime());
			int oldDate = cal.get(Calendar.DAY_OF_MONTH);

			int newDate = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
			if(oldDate == newDate){
				if(MobileForRedis.MAXSENDTIMESONEDAY >= sendTimes){
					oldMobile.setSendTimes(sendTimes + 1);
					// oldMobile.setIdentifyingCode(code);
					oldMobile.setLastSendTime(Calendar.getInstance().getTime());

					// sendInfoService.sendTextMessage(mobileNum, code,
					// SendTextMessageType.SENDREGISTERTEXTMESSAGE.getTextMessageType());

					ValidateCodeSend validateCodeSend = new ValidateCodeSend();
					validateCodeSend.setSendIdentity(mobileNum);
					validateCodeSend.setSendType(SendTypeEnum.SMS);
					validateCodeSend.setBizType(type);
					validateCodeSend.setEffectMinute(2);
					//FIXME 演示需要 增加code
					String code = validateCodeSendService
							.createAndSendCheckCode(validateCodeSend).getResultCode();
				//	result.setResultCode(code);
					defaultCache.add(key, oldMobile, 1*3600*24);
				}else {
					result.setSuccess(false);
					result.addMsg("每天只能发送十次");
					//logger.debug("每天只能发送十次");
				}
			}else{
				MobileForRedis mobile = new MobileForRedis();
				mobile.setUmobile(mobileNum);
				mobile.setSendTimes(1);
				mobile.setLastSendTime(Calendar.getInstance().getTime());
				mobile.setCreateTime(Calendar.getInstance().getTime());

				ValidateCodeSend validateCodeSend = new ValidateCodeSend();
				validateCodeSend.setSendIdentity(mobileNum);
				validateCodeSend.setSendType(SendTypeEnum.SMS);
				validateCodeSend.setBizType(type);
				validateCodeSend.setEffectMinute(2);
				//FIXME 演示需要
				String code = validateCodeSendService.createAndSendCheckCode(validateCodeSend).getResultCode();
				//result.setResultCode(code);
				defaultCache.add(key, mobile, 1*3600*24);
			}
			
		} else {
			MobileForRedis mobile = new MobileForRedis();
			mobile.setUmobile(mobileNum);
			mobile.setSendTimes(1);
			mobile.setLastSendTime(Calendar.getInstance().getTime());
			mobile.setCreateTime(Calendar.getInstance().getTime());

			ValidateCodeSend validateCodeSend = new ValidateCodeSend();
			validateCodeSend.setSendIdentity(mobileNum);
			validateCodeSend.setSendType(SendTypeEnum.SMS);
			validateCodeSend.setBizType(type);
			validateCodeSend.setEffectMinute(2);
			//FIXME 演示需要
			String code = validateCodeSendService.createAndSendCheckCode(validateCodeSend).getResultCode();
			//result.setResultCode(code);
			defaultCache.add(key, mobile, 1*3600*24);
		}

		return result;
	}
	
	
	/**
	 * 邮箱发送验证码
	 */
	@Override
	public UserCenterResult sendCodeByEmail(String email, String key,
			BizTypeEnum type, int codeType) {
		UserCenterResult result = new UserCenterResult(true,
				new ArrayList<String>());
		UserCenterResult checkResult = userRegisterCheckService
				.checkMobileOrEmailExist(StringUtils.EMPTY,email, codeType);
		if (!checkResult.isSuccess()) {
			result.setSuccess(false);
			result.addMsg(checkResult.getMsgs().get(0));
			return result;
		}

		key += email;
		MobileForRedis oldMobile = (MobileForRedis) defaultCache.getValue(key);
		if (oldMobile != null
				&& StringUtils.isNoneEmpty(oldMobile.getUmobile())) {
			Integer sendTimes = oldMobile.getSendTimes();

			Calendar cal = Calendar.getInstance();
			cal.setTime(oldMobile.getCreateTime());
			int oldDate = cal.get(Calendar.DAY_OF_MONTH);

			int newDate = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
			if (oldDate == newDate){
				if(MobileForRedis.MAXSENDTIMESONEDAY >= sendTimes){
					oldMobile.setSendTimes(sendTimes + 1);
					// oldMobile.setIdentifyingCode(code);
					oldMobile.setLastSendTime(Calendar.getInstance().getTime());

					// sendInfoService.sendTextMessage(mobileNum, code,
					// SendTextMessageType.SENDREGISTERTEXTMESSAGE.getTextMessageType());

					ValidateCodeSend validateCodeSend = new ValidateCodeSend();
					validateCodeSend.setSendIdentity(email);
					validateCodeSend.setSendType(SendTypeEnum.EMAIL);
					validateCodeSend.setBizType(type);
					validateCodeSend.setEffectMinute(2);
					//FIXME 演示需要 增加code
					String code = validateCodeSendService
							.createAndSendCheckCode(validateCodeSend).getResultCode();
					//result.setResultCode(code);
					defaultCache.add(key, oldMobile, 1*60);
				}else {
					result.setSuccess(false);
					result.addMsg("每天只能发送十次");
					
				}
			}else{
				MobileForRedis mobile = new MobileForRedis();
				mobile.setUmobile(email);
				mobile.setSendTimes(1);
				mobile.setLastSendTime(Calendar.getInstance().getTime());
				mobile.setCreateTime(Calendar.getInstance().getTime());

				ValidateCodeSend validateCodeSend = new ValidateCodeSend();
				validateCodeSend.setSendIdentity(email);
				validateCodeSend.setSendType(SendTypeEnum.EMAIL);
				validateCodeSend.setBizType(type);
				validateCodeSend.setEffectMinute(2);
				//FIXME 演示需要
				String code = validateCodeSendService.createAndSendCheckCode(validateCodeSend).getResultCode();
				//result.setResultCode(code);
				defaultCache.add(key, mobile, 1*3600*24);
			}
			
		} else {
			MobileForRedis mobile = new MobileForRedis();
			mobile.setUmobile(email);
			mobile.setSendTimes(1);
			mobile.setLastSendTime(Calendar.getInstance().getTime());
			mobile.setCreateTime(Calendar.getInstance().getTime());

			ValidateCodeSend validateCodeSend = new ValidateCodeSend();
			validateCodeSend.setSendIdentity(email);
			validateCodeSend.setSendType(SendTypeEnum.EMAIL);
			validateCodeSend.setBizType(type);
			validateCodeSend.setEffectMinute(2);
			//FIXME 演示需要
			String code = validateCodeSendService.createAndSendCheckCode(validateCodeSend).getResultCode();
			//result.setResultCode(code);
			defaultCache.add(key, mobile, 1*3600*24);
		}

		return result;
	}

	private UserCenterResult checkRegiser(UserRegisterVo userRegisterVo) {
		String umobile = userRegisterVo.getUmobile();
		Integer registerType = userRegisterVo.getRegisterType();
		UserCenterResult result = null;
		if (Integer.valueOf(RegisterType.MOBILEREGISTER.getRegisterType())
				.equals(registerType)) {
			result = userRegisterCheckService.checkMobileOrEmailExist(umobile,
					StringUtils.EMPTY);
		} else {
			result = userRegisterCheckService.checkMobileOrEmailExist(
					StringUtils.EMPTY, userRegisterVo.getUemail());
		}
		// 验证码
		String identifyingCode = userRegisterVo.getIdentifyingCode();
		if (result.isSuccess()) {
			if (Integer.valueOf(RegisterType.MOBILEREGISTER.getRegisterType())
					.equals(registerType)) {

				ValidateCodeSend validateCodeSend = new ValidateCodeSend();
				validateCodeSend.setSendIdentity(umobile);
				validateCodeSend.setSendType(SendTypeEnum.SMS);
				validateCodeSend.setBizType(BizTypeEnum.MobileBinding);
				ValidateCodeSendResult valResult = validateCodeSendService
						.check(validateCodeSend, identifyingCode);
				if (!valResult.isSuccess()) {
					result.setSuccess(false);
					result.addMsg(valResult.getResultCode());
				}
			}
		}
		return result;
	}

	/**
	 * 校验发送邮件
	 * 
	 * @author
	 * @param emailAddress
	 * @param type
	 * @return
	 */
	private UserCenterResult checkSendEmail(String emailAddress, int type) {
		UserCenterResult result = new UserCenterResult(true,
				new ArrayList<String>());
		// 判断数据库该邮箱是否已经存在
		UserCenterResult checkResult = userRegisterCheckService
				.checkMobileOrEmailExist(StringUtils.EMPTY, emailAddress, type);
		if (!checkResult.isSuccess()) {
			result.setSuccess(false);
			result.addMsg(checkResult.getMsgs().get(0));
			return result;
		}
		String key = "sendIdentifyingEmail_" + emailAddress;
		RegisterEmailForRedis oldRegEmail = (RegisterEmailForRedis) defaultCache
				.getValue(key);
		if (oldRegEmail != null
				&& StringUtils.isNotEmpty(oldRegEmail.getEmailAddress())) {
			int sendTimes = oldRegEmail.getSendTimes();
			Calendar cal = Calendar.getInstance();
			cal.setTime(oldRegEmail.getCreateTime());
			int oldDate = cal.get(Calendar.DAY_OF_MONTH);
			int newDate = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
			if (oldDate == newDate){
				if(RegisterEmailForRedis.MAXSENDTIMESONEDAY >= sendTimes){
					oldRegEmail.setSendTimes(sendTimes + 1);
					oldRegEmail.setLastSendTime(Calendar.getInstance().getTime());
					defaultCache.add(key, oldRegEmail, 1*3600*24);
				} else {
					result.setSuccess(false);
					result.addMsg("每天只能发送十次");
				}
			}
			else{
				oldRegEmail = new RegisterEmailForRedis();
				oldRegEmail.setCreateTime(Calendar.getInstance().getTime());
				oldRegEmail.setLastSendTime(Calendar.getInstance().getTime());
				oldRegEmail.setEmailAddress(emailAddress);
				oldRegEmail.setSendTimes(1);
				defaultCache.add(key, oldRegEmail, 1*3600*24);
			}
					
				
			
		} else {
			oldRegEmail = new RegisterEmailForRedis();
			oldRegEmail.setCreateTime(Calendar.getInstance().getTime());
			oldRegEmail.setLastSendTime(Calendar.getInstance().getTime());
			oldRegEmail.setEmailAddress(emailAddress);
			oldRegEmail.setSendTimes(1);
			defaultCache.add(key, oldRegEmail, 1*3600*24);
		}
		return result;
	}

	@Override
	@Transactional
	public UserCenterResult checkRegisterEmailLegal(String encryptEmailId,
			String encryptCode, String sendEmailType, String encryptUserId) {
		UserCenterResult result = new UserCenterResult(true,
				new ArrayList<String>());
		String emailCodeID = Encrypter.decrypt(encryptEmailId);
		String code = Encrypter.decrypt(encryptCode);
		String userId = "";
		if (!StringUtils.isEmpty(encryptUserId)) {
			userId = Encrypter.decrypt(encryptUserId);
		}
		EmailCode emailCode = emailCodeService.getEmailCodeById(emailCodeID);
		if (emailCode != null
				&& StringUtils.equalsIgnoreCase(code, emailCode.getCode())) {
			Long expire = emailCode.getExpire();
			Long currentTime = Calendar.getInstance().getTimeInMillis();
			if (currentTime.longValue() > expire) {
				result.setSuccess(false);
				result.addMsg("链接已过期");
				return result;
			} else {
				result.addMsg(emailCode.getEmail());
				emailCode.setStatus(EmailCode.Status.VALIDITY.getStatus());
				emailCodeService.updateEmailCode(emailCode);
			}
			if (Integer.valueOf(sendEmailType) == SendEmailTypeEnum.TYPE_NEWEMAIL
							.getIndex()) {
				User user = new User();
				user.setUid(userId);
				user.setUemail(emailCode.getEmail());
				userDao.update(user);
				userInfoAuthService.saveEmailAuth(userId);
			}
		} else {
			result.setSuccess(false);
			result.addMsg("邮箱验证失败");
		}
		return result;
	}

	@Override
	@Transactional
	public void doRegisterByMobile(UserRegisterVo userRegisterVo) {
		Integer registerType = userRegisterVo.getRegisterType();
		String password = userRegisterVo.getPassword();

		User user = new User();
		String umobile = userRegisterVo.getUmobile();
		String uemail = userRegisterVo.getUemail();
		user.setUid(userSequenceService.getNextUserId());
		userRegisterVo.setUid(user.getUid());
		if (Integer.valueOf(RegisterType.MOBILEREGISTER.getRegisterType())
				.equals(registerType)) {
			user.setUmobile(umobile);
			// 手机注册，邮箱写当前时间
			/*user.setUemail(String.valueOf(Calendar.getInstance()
					.getTimeInMillis()));*/
			List<AuthValue> authValueList = new ArrayList<AuthValue>();
			AuthValue mobileAuth = new AuthValue(UserAuthName.AUTH_MOBILE,
					AuthStatus.AUTHSUCCESS.getAuthStatus());
			authValueList.add(mobileAuth);
			userInfoAuthService.saveAuthByAuthValueList(user.getUid(),
					authValueList);
		} else {
			// 邮箱注册
			user.setUemail(uemail);
			user.setUmobile(String.valueOf(Calendar.getInstance()
					.getTimeInMillis()));
			userInfoAuthService.saveEmailAuth(user.getUid());
		}
		String uname = userRegisterVo.getUname();
		user.setPassword(MD5Util.sha1(password));
		user.setUname(uname);
		userDao.save(user);
		openAccount(user.getUid()); 

	}

	@Override
	public UserCenterResult sendEmail(String emailAddress, String code,
			int type, String url, String userId) {
		UserCenterResult result = checkSendEmail(emailAddress, type);
		if (result.isSuccess()) {
			EmailCode emailCode = emailCodeService.saveEmailCode(emailAddress,
					code, 24, type);
			String targetUrl = MobileUtils.createEmailUrl(emailCode.getId(),
					code, url, type, userId);
			sendInfoService.sendEmail(emailAddress, targetUrl,
					SendTextMessageType.SENDREGISTERIDENTIFYINGEMAIL
							.getTextMessageType());
		}
		return result;
	}

	@Override
	public UserCenterResult checkSMSCode(String mobilephone, String code,
			BizTypeEnum bizType) {
		UserCenterResult userCenterResult = new UserCenterResult();
		ValidateCodeSend validateCodeSend = new ValidateCodeSend();
		validateCodeSend.setSendIdentity(mobilephone);
//		validateCodeSend.setSendType(SendTypeEnum.SMS);
		validateCodeSend.setBizType(bizType);
		ValidateCodeSendResult valResult = validateCodeSendService.check(
				validateCodeSend, code);
		if (!valResult.isSuccess()) {
			userCenterResult.setSuccess(false);
			userCenterResult.addMsg(valResult.getResultCode());
		} else {
			userCenterResult.setSuccess(true);
		}
		return userCenterResult;
	}
	
	private void openAccount(String uid){
		
		User authIdUser = new User();
		AccountOpenResult accountOpenResult = remotAccountOpenFacade
				.openAccountForUser(uid, new HashMap<String, Object>());
		if (accountOpenResult.isSuccess()) {
			String accountNo = accountOpenResult.getAccountNo();
			authIdUser.setUid(uid);
			authIdUser.setAccountNo(accountNo);
			userDao.updateAccountNo(authIdUser);
			userCreditsService.create(uid, UserCreditsType.UserCreditsNeedCharge, 0l);
		}
	}

	@Override
	public void addCardId(String real_name, String card_id) {
		// TODO Auto-generated method stub
		BaseUser u = (BaseUser)LoginUtil.getCurrentUser();
		userDao.addCardInfo(real_name,card_id,u.getId());
		
	}

}
